"""
该模块提供了与网页进行交互的功能。
"""

import logging
import time
from selenium import webdriver
from selenium.common import (
    NoSuchElementException,
    TimeoutException,
    StaleElementReferenceException,
)
from selenium.webdriver.edge.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from config import (
    WEB_DRIVER_PATH,
    START_URL,
    JOURNAL_SEARCH_SELECTOR,
    MAJOR_SEARCH_SELECTOR,
    DELAY,
    TEXT_AREA_SELECTOR,
    CHECKBOX,
    START_YEAR_SELECTOR,
    END_YEAR_SELECTOR,
    END_YEAR,
    START_YEAR,
    START_SEARCH_BUTTON_SELECTOR,
    JOURNAL_QUALITY_SELECTOR,
)
from web_driver_factory import WebDriverFactory


class WebDriverHandler:
    """与网页交互处理类"""

    def __init__(self):
        """初始化WebDriver和选项。"""
        self.driver = WebDriverFactory.create_webdriver()

    def open_search_page(self):
        """
        打开搜索页面。

        返回值:
            bool: 如果找到并点击期刊选项则返回True，否则返回False。
        """
        logging.info("成功加载 CNKI 页面.")
        self.driver.get(START_URL)
        try:
            self.wait_for_element(JOURNAL_SEARCH_SELECTOR).click()

            major_search = self.wait_for_element(MAJOR_SEARCH_SELECTOR)
            if major_search:
                major_search.click()
                logging.info("成功执行检索式")
            else:
                logging.warning("未找到文献内容")
        except NoSuchElementException:
            return False

        return True

    def wait_for_element(self, selector):
        """
        等待页面上的单个元素出现。
        """
        # logging.info(f"Waiting for element with selector: {selector}")
        try:
            element = WebDriverWait(self.driver, DELAY).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, selector))
            )
            # logging.info(f"Element found: {selector}")
            return element
        except TimeoutException:
            logging.error(
                f"TimeoutException: Element not found within {DELAY} seconds: {selector}"
            )
        except StaleElementReferenceException:
            logging.error(
                f"StaleElementReferenceException: Element is no longer "
                f"attached to the DOM: {selector}"
            )
        except NoSuchElementException:
            logging.error(f"NoSuchElementException: Element not found: {selector}")
        except Exception as e:
            logging.error(
                f"Exception: An unexpected error occurred while waiting for element: {selector}, Error: {e}"
            )
        return None

    def wait_for_elements(self, selector):
        """
        等待页面上的多个元素出现。
        """
        # logging.info(f"Waiting for elements with selector: {selector}")
        try:
            elements = WebDriverWait(self.driver, DELAY).until(
                EC.presence_of_all_elements_located((By.CSS_SELECTOR, selector))
            )
            # logging.info(f"Elements found: {selector}, Count: {len(elements)}")
            return elements
        except TimeoutException:
            logging.error(
                f"TimeoutException: Elements not found within {DELAY} seconds: {selector}"
            )
        except StaleElementReferenceException:
            logging.error(
                f"StaleElementReferenceException: Elements are no longer attached to the DOM: {selector}"
            )
        except NoSuchElementException:
            logging.error(f"NoSuchElementException: Elements not found: {selector}")
        except Exception as e:
            logging.error(
                f"Exception: An unexpected error occurred while waiting for elements: {selector}, Error: {e}"
            )
        return None

    def scroll_page(self, times, pause_duration=1):
        """
        自动向下滚动页面指定次数。
        """

        for _ in range(times):
            body = self.wait_for_element("body")
            scroll_flag = self.wait_for_element("#literature-recommend > h5 > span > b")
            if scroll_flag:
                body.send_keys(Keys.PAGE_DOWN)
            time.sleep(pause_duration)

    def switch_to_new_window(self, current_handle, driver):
        """
        切换到新窗口。

        参数:
            current_handle (str): 当前窗口的句柄。
            driver (WebDriver): 用于与网页交互的WebDriver实例。

        返回值:
            str: 如果找到新窗口则返回新窗口的句柄，否则返回None。
        """
        all_windows = driver.window_handles
        try:
            for window in all_windows:
                if window != current_handle:
                    driver.switch_to.window(window)
                    return window
        except NoSuchElementException:
            logging.error("未成功切换到文献窗口界面")
        return None

    def execute_search(self, search_query):
        """
        配置搜索详细查询并开始搜索。

        参数:
            search_query (str): 搜索查询字符串。

        返回值:
            无
        """
        # 输入搜索查询
        self.wait_for_element(TEXT_AREA_SELECTOR).send_keys(search_query)
        # 选择期刊级别
        self.journal_level(CHECKBOX)
        # 输入搜索时间范围
        self.wait_for_element(START_YEAR_SELECTOR).send_keys(START_YEAR)
        self.wait_for_element(END_YEAR_SELECTOR).send_keys(END_YEAR)
        # 开始搜索
        self.wait_for_element(START_SEARCH_BUTTON_SELECTOR).click()

        # 设置CNKI上的学科分类，以【图书情报与数字图书馆】为例
        # self.wait_for_element(ARTICLE_LIST).click()
        # self.wait_for_element(ARTICLE_LIST_INFORMATION_TEC).click()
        # self.wait_for_element(ARTICLE_CATALOG_LIS).click()

    def find_and_click(self, selector):
        """
        与可点击的元素进行交互
        """
        element = self.wait_for_element(selector)
        if element:
            element.click()

    def journal_level(self, checkboxes):
        """
        选择期刊级别：
        - 北大核心：HX
        - 南大核心：CSI
        - 在 config.py 中加以设置
        """
        for checkbox in checkboxes:
            self.find_and_click(f"{JOURNAL_QUALITY_SELECTOR}[key='{checkbox}']")
